#pragma once
#include <thread>
#include <mutex>
#include <vector>
#include <queue>
#include <atomic>
#include <functional>
#include <condition_variable>
#include <map>
#include <future>
#include <memory>
using namespace std;

/*
构成：
 1. 管理这者线程---> 子线程 1个
    - 控制工作线程的数量：增加或减少
 2. 若干工作线程 ---> 子线程n个
    -从任务队列中取任务，并处理
    -任务队列为空，被阻塞（被条件变量阻塞）
    -线程同步（互斥锁）
    -当前数量，空闲的线程数量
    -最小，最大线程数量
 3. 任务队列---> stl——>queue
    -互斥锁
    -条件变量
 4. 线程池开关——> bool
*/

// 线程池类
class ThreadPool
{
public:
    ThreadPool(int min = 4, int max = thread::hardware_concurrency());
    ~ThreadPool();
    // 添加任务  ---> 任务队列
    // void addTask(function<void()> f);

    template<typename F, typename... Args>
    auto addTask(F&& f,Args&&... args) -> future<typename result_of<F(Args...)>::type> {
        // 1. package_task
        using returnType = typename result_of<F(Args...)>::type;
        auto mytask = make_shared<packaged_task<returnType()>>(
            bind(forward<F>(f), forward<Args>(args)...) //forward 完美转发，保证数据的原始类型
        );
        // 2. 得到future
        future<returnType> res = mytask->get_future();
        // 3. 任务函数添加到任务队列

        m_queueMutex.lock();
        m_tasks.emplace([mytask](){
            (*mytask)();
        });// mytask是指针  避免内存泄漏   共享资源
        m_queueMutex.unlock();

        m_condition.notify_one();// 唤醒一个线程
        return res;
    }
private:
    void manager();
    void worker();
private:
    thread* m_manager;
    map<thread::id, thread> m_workers; 
    vector<thread::id> m_ids; 
    int m_minThreads;
    int m_maxThreads; 
    atomic<bool> m_stop; 
    atomic<int> m_curThreads;
    atomic<int> m_idleThreads;
    atomic<int> m_exitNumber; 
    queue<function<void()>> m_tasks;
    mutex m_idsMutex; 
    mutex m_queueMutex;
    condition_variable m_condition;
};
